//
//	A Visible View
//	Randy NelsonÐCopyright NeXT 1990
//	Not for release or reuse
//

#import "VisibleOne.h"
#import <appkit/View.h>
#import <appkit/publicWraps.h>
#import <dpsclient/wraps.h>
#import <appkit/graphics.h>
#import <appkit/Application.h>
#import <appkit/Font.h>
#import <appkit/Form.h>
#import <appkit/Control.h>
#import <appkit/Button.h>
#import <appkit/Bitmap.h>
#import <appkit/nextstd.h>
#import <libc.h>
#import "SubViewFramer.h"
#import "Appender.h"
#import	"Timing.h"

@implementation VisibleOne

#define TIMING_DEBUG		1


//factory methodÐsets clipping off
+ newFrame:(NXRect *)f
{
	self = [super newFrame:f];
	[self setClipping:NO];
	return self;
}

//outlet initializers
- setAppender:anObject
{
	appender = anObject;
	return self;
}

- setTransparencyIndicator:anObject
{
	transparencyIndicator = anObject;
	return self;
}

- setCompositeIndicator:anObject
{
	compositeIndicator = anObject;
	return self;
}

- setDrawGridIndicator:anObject
{
	drawGridIndicator = anObject;
	return self;
}

- setFrameX:anObject
{
	frameX = anObject;
	return self;
}

- setFrameY:anObject
{
	frameY = anObject;
	return self;
}

- setFrameWidth:anObject
{
	frameWidth = anObject;
	return self;
}

- setFrameHeight:anObject
{
	frameHeight = anObject;
	return self;
}

- setScaleX:anObject
{
    scaleX = anObject;
    return self;
}

- setTranslateY:anObject
{
    translateY = anObject;
    return self;
}

- setVitalMatrix:anObject
{
    vitalMatrix = anObject;
    return self;
}

- setTranslateX:anObject
{
    translateX = anObject;
    return self;
}

- setScaleY:anObject
{
    scaleY = anObject;
    return self;
}

//translate
- setSelfOrigin:sender
{
	[self setDrawOrigin:[translateX intValue] :[translateY intValue]];
	[window display];
	return self;
}

//scale
- setSelfScale:sender
{
	[self scale:[scaleX floatValue] :[scaleY floatValue]];
	[window display];

	//reset the interface values
	[scaleX setIntValue:1];
	[scaleY setIntValue:1];
	
	return self;
}

//rotate
- setSelfRotation:sender
{
	[self setDrawRotation:[sender intValue]];
	[window display];
	return self;
}

//move frame
- frameMove:sender
{
	[self moveTo:[frameX floatValue] :[frameY floatValue]];
	[window display];
	[self setTrackingRect];
	return self;
}

//rotate frame
- frameRotate:sender
{
	[self rotateTo:[sender intValue]];
	[window display];
	/*if ([self frameAngle] == 0){
		[self setTrackingRect];
	}
	else{
		[window discardTrackingRect:23];
	}
	*/
	return self;
}

//resize frame
- frameChangeSize:sender
{
	[self sizeTo:[frameWidth intValue] :[frameHeight intValue]];
	[window display];
	[self setTrackingRect];
	return self;
}

//sent by the preferences buttons to force a redraw, reflecting their new state
- newDisplayState:sender
{
	[window display];
	return self;
}

//delegate method of app
- appDidInit:sender
{
	NXRect aRect = {0.0, 0.0, 0.0, 0.0};
	sprintf(buffer, "Received appDidInit:\n");	
	[appender appendToText:buffer];
	
	//gets the bitmap for compositing
	myPic = [Bitmap findBitmapFor:"nextLogo"];
	
	//sets up the subViewFramer as our superview
	newSuperView = [SubViewFramer newFrame:&aRect];
	[window setContentView:newSuperView];
	[newSuperView addSubview:self];
	[newSuperView display];
		
	[self setTrackingRect];
	[window makeKeyAndOrderFront:self];
	return self;
}

//allows us to become first responder
- (BOOL)acceptsFirstResponder
{
	sprintf(buffer, "Received acceptsFirstResponder -- returning YES\n");	
	[appender appendToText:buffer];
	return YES;
}

//allows us to use the mouse click that activates the window
- (BOOL)acceptsFirstMouse
{
	sprintf(buffer, "Received acceptsFirstMouse -- returning YES\n");	
	[appender appendToText:buffer];
	return YES;
}

//draws the view and then calls the superview for framing
- drawSelf:(NXRect *)r :(int)c
{
	NXPoint zero = {0.0, 0.0};

	[self updateVitals];
	if([compositeIndicator state]){
		[myPic composite:NX_COPY toPoint:&zero];
	}
	if([drawGridIndicator state]){
		PSselectfont("Times-Italic", 24.0);
		PSsetgray(NX_WHITE);
		[self drawGrid];
	}
	//draws the views basic contents
	[self drawSomePS];
	
	//displays the bounds rect
	PSsetgray(NX_BLACK);
	sprintf(buffer, "bounds.origin.x %.1f,.y %.1f", bounds.origin.x, bounds.origin.y);
	PSmoveto(bounds.origin.x, (bounds.origin.y - 18));
	PSselectfont("Times-Italic", 24.0);
	PSshow(buffer);
	NXFrameRect(&bounds);
	
	//calls the subViewFramer, our superview
	[newSuperView frameMe:self];
	
	return self;
}

//indicates the mouse down with a beep
- mouseDown:(NXEvent *)e
{
	sprintf(buffer, "Received mouseDown: -- window coordinates %.f, %.f\n", e->location.x, e->location.y);	
	[appender appendToText:buffer];
	NXBeep();
	return self;
}

//indicates at the location of the mouse at mouse up using instance drawing
- mouseUp:(NXEvent *)e
{
	
	NXPoint mousePoint = e->location;

	sprintf(buffer, "Received mouseUp: -- window coordinates %.f, %.f\n", e->location.x, e->location.y);
	[appender appendToText:buffer];
	[self convertPointFromSuperview:&mousePoint];
	[self lockFocus];
	PSselectfont("Times-Italic", 24.0);
	PSsetgray(NX_DKGRAY);
	PSnewinstance();
	PSsetinstance(YES);
	PSmoveto(mousePoint.x, mousePoint.y);
	PSsetgray(0.0);
	PSrectfill(mousePoint.x-2.0, mousePoint.y-2.0, 4.0, 4.0);
	PSmoveto(mousePoint.x+4.0, mousePoint.y+4.0);
	sprintf(buffer, "%.f, %.f", mousePoint.x, mousePoint.y);
	PSshow(buffer);
	PSsetinstance(NO);
	[self unlockFocus];
	return self;
}

//tracks the mouse entering the view
- mouseEntered:(NXEvent *)e
{
	sprintf(buffer, "Received mouseEntered: -- window coordinates %.f, %.f\n", e->location.x, e->location.y);
	[appender appendToText:buffer];
	return self;
}

//tracks the mouse leaving the view
- mouseExited:(NXEvent *)e
{
	sprintf(buffer, "Received mouseExited: -- window coordinates %.f, %.f\n", e->location.x, e->location.y);
	[appender appendToText:buffer];
	return self;
}

//gets keyUps
- keyUp:(NXEvent *)e
{
	sprintf(buffer, "Received keyUp:\n");
	[appender appendToText:buffer];
	return self;
}

//gets keyDowns
- keyDown:(NXEvent *)e
{
	sprintf(buffer, "Received keyDown: -- char '%c'\n", e->data.key.charCode);
	[appender appendToText:buffer];
	return self;
}

//checks to see if the mouse down was in this view
- hitTest:(NXPoint *)aPt
{
	char *localBuffer;
	
	NX_MALLOC(localBuffer, char, 100);
	
	sprintf(localBuffer, "Received hitTest:");
	[appender appendToText:localBuffer];
	if ([super hitTest:aPt]){
		sprintf(localBuffer, " -- YES inside this view\n");
		[appender appendToText:localBuffer];
		return self;
	}
	sprintf(localBuffer, " -- NO not inside this view\n");	 
	[appender appendToText:localBuffer];
	return  nil;
}

//updates the statistics matrix
- updateVitals
{
	[[[[[[[[[[vitalMatrix setFloatValue:bounds.origin.x at:0]
		setFloatValue:bounds.origin.y at:1]
			setFloatValue:bounds.size.width at:2]
				setFloatValue:bounds.size.height at:3]
					setFloatValue:[self boundsAngle] at:4]
						setFloatValue:frame.origin.x at:5]
							setFloatValue:frame.origin.y at:6]
								setFloatValue:frame.size.width at:7]
									setFloatValue:frame.size.height at:8]
										setFloatValue:[self frameAngle] at:9];
	return self;
}

//for communication with the transparent superview
- (BOOL)wantsTransparency
{
	return ([transparencyIndicator state]);
}

- setTrackingRect
{
	NXRect aRect;
	
	//registers the tracking rect
	aRect = frame;
	[superview convertRect:&aRect toView:nil];
	sprintf(buffer, "Sending setTrackingRect:... to window\n");	
	[appender appendToText:buffer];
	[window setTrackingRect:&aRect inside:NO owner:self tag:23 left:NO right:NO];
	return self;
}

- drawGrid
{
#ifdef TIMING_DEBUG
	id t4 = [Timing newWithTag:4];
	[t4 reset];
	[t4 enter:PSTIME];
#endif
	
    PSrectstroke(0.0, 0.0, 100.0, 100.0); 
    PSrectstroke(100.0, 100.0, 100.0, 100.0); 
    PSrectstroke(0.0, 0.0, 200.0, 200.0); 
    PSmoveto (0.0, 0.0 ); 
    PSshow("0.0 0.0");
    PSmoveto(100.0, 100.0 );
    PSshow ("100.0, 100.0"); 
    PSmoveto (200.0, 200.0); 
    PSshow("200.0, 200.0");
    PSrectstroke(0.0, 0.0, -100.0, -100.0);
    PSrectstroke(-100.0, -100.0, -100.0, -100.0 ); 
    PSrectstroke (0.0, 0.0, -200.0, -200.0); 
    PSmoveto(-100.0, -100.0 ); 
    PSshow("-100.0, -100.0");
    PSmoveto(-200.0, -200.0 ); 
    PSshow("-200.0, -200.0");
    PSrectstroke(0.0, 0.0, -100.0, 100.0); 
    PSrectstroke(-100.0, 100.0, -100.0, 100.0);
    PSrectstroke( 0.0, 0.0, -200.0, 200.0);
    PSmoveto(-100.0 , 100.0 ); 
    PSshow("-100.0, 100.0");
    PSmoveto(-200.0, 200.0); 
    PSshow("-200.0, 200.0");
    PSrectstroke( 0.0, 0.0, 100.0, -100.0 );
    PSrectstroke(100.0, -100.0, 100.0, -100.0);
    PSrectstroke( 0.0, 0.0, 200.0, -200.0 );
    PSmoveto (100.0, -100.0 );
    PSshow("100.0, -100.0");
    PSmoveto( 200.0, -200.0); 
    PSshow("200.0, -200.0");
	
	
#ifdef TIMING_DEBUG
	[t4 leave];
	[t4 summary:self];
#endif

    return self;
}

//defs
- tripath
{
    PSmoveto(0.0, 0.0);
    PSlineto(100.0, 0.0);
    PSlineto(50.0, 100.0);
    PSclosepath();
    return self;
} 

- cirpath
{
    PSmoveto(100.0, 50.0);
    PSarc(50.0, 50.0, 50.0, 0.0, 360.0);
    return self;
}

- recstroke
{
    PSrectstroke(0.0, 0.0, 100.0, 100.0);
    return self;
} 

- recfill
{
    PSrectfill(0.0, 0.0, 100.0, 100.0);
    return self;
}

- rec
{
    PSsetgray(.333);
    [self recfill];
    PSsetgray(0.0);
    [self recstroke];
    return self;
}

- cir
{
    PSsetgray(.5);
    [self cirpath];
    PSfill();
    PSsetgray(0.0);
    [self cirpath];
    PSstroke();
    return self;
}

- tri
{
    PSsetgray(.666);
    [self tripath];
    PSfill();
    PSsetgray(0.0);
    [self tripath];
    PSstroke();
    return self;
}

- mass
{
    [self rec];
    [self cir];
    [self tri];
    return self;
}

//body
- drawSomePS
{	
    PSgsave();
    PStranslate(200.0, 50.0); 
    PSrotate(30.0);
    [self mass];
    PSgrestore();
    
    PSgsave();
    PStranslate(150.0, 50.0);
    PSrotate(45.0);
    [self rec];
    PSgrestore();
    
    PSgsave();
    PStranslate(50.0, 150.0);
    [self tri];
    PSgrestore();
    
    PSgsave();
    PStranslate(100.0, 100.0);
    [self cir];
    PSgrestore();
    
    PSgsave();
    PStranslate(25.0, 25.0);
    [self mass];
    PSgrestore();
    
    PSgsave();
    PStranslate(125.0, 275.0);
    PSrotate(-60.0);
    [self mass];
    PSgrestore();

    return self;
}
@end
